package com.robcity.platform.config;



import com.robcity.platform.component.RestTemplateInterceptor;
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.List;

@Configuration
public class RestTemplateConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateConfig.class);

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient);
        // 连接超时时间，毫秒
        factory.setConnectTimeout(20_000);
        // 读取超时时间，毫秒
        factory.setReadTimeout(60_000);
        // 从连接池获取连接的等待时间，毫秒
        factory.setConnectionRequestTimeout(30_000);
        return new BufferingClientHttpRequestFactory(factory);
    }

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory){
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        // UTF-8
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (HttpMessageConverter<?> converter : messageConverters) {
            if (converter instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
            }
        }
        // 日志拦截器
        restTemplate.getInterceptors().add(new RestTemplateInterceptor());
        return restTemplate;
    }

    @Bean
    public HttpClient httpClient() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

        SSLContext sslContext;
        SSLConnectionSocketFactory sslConnectionSocketFactory = null;
        try {
            // 设置跳过证书验证，信任所有
            sslContext = SSLContexts.custom().loadTrustMaterial(null, (X509Certificate[] var1, String var2) -> true).build();

            sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            LOGGER.error("SSLContext loadTrustMaterial error, {}", e.getMessage());
        }

        // 注册 http, https
        RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
        registryBuilder.register("http", PlainConnectionSocketFactory.getSocketFactory());
        if (sslConnectionSocketFactory != null) {
            registryBuilder.register("https", sslConnectionSocketFactory);
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry = registryBuilder.build();

        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        // 最大tcp连接数：1000
        poolingHttpClientConnectionManager.setMaxTotal(10_000);
        // 同路由最大tcp连接数：800
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(8_00);
        // 配置连接池
        httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
        // 允许重试，重试次数：3
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));
        return httpClientBuilder.build();
    }


}
